<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Images in Java 2D</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Java2D, Java, tutorial, images, programming, GUI, multiplatform">
<meta name="description" content="In this part of the Java 2D tutorial, we work with images.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>


<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>



<h1>Images in Java 2D</h1>


<p>
In this part of the Java 2D tutorial, we will work with images. 
Images are really a complex topic. Here we can only scratch the surface. 
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
<code>BufferedImage</code> plays a crucial role when we work 
with images in Java 2D. It is used to manipulate with images. 
It is created in memory for efficiency. The process is as follows. 
We copy the image pixels into the BufferedImage, manipulate the pixels 
and draw the result on the panel. 
</p>


<h2>Displaying an Image</h2>


<p>
In the first example, we simply display an image on the panel. 
</p>

<div class="codehead">DisplayImage.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DisplayImage extends JPanel {

   Image castle;
   Dimension size;

    public DisplayImage() {
        size = new Dimension();
        castle = new ImageIcon(this.getClass().getResource("redrock.png")).getImage();
        size.width = castle.getWidth(null);
        size.height = castle.getHeight(null);
        setPreferredSize(size);
    }

    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        g2d.drawImage(castle, 0, 0, null);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Red Rock");
        frame.add(new DisplayImage());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
In our example, we show the Red Rock castle on the panel. 
It is a beautiful medieval castle located in the
west part of Slovakia. 
</p>


<pre class="explanation">
castle = new ImageIcon(this.getClass().getResource("redrock.png")).getImage();
</pre>

<p>
We use the <code>ImageIcon</code> class to load the image. 
</p>

<pre class="explanation">
g2d.drawImage(castle, 0, 0, null);
</pre>

<p>
The <code>drawImage()</code> method draws the image 
on the panel at the specified position.
The last parameter is the <code>ImageObserver</code> class. 
It is sometimes used for asynchronous loading.
When we do not need asynchronous loading of our images, we can just put null there. 
</p>

<img src="/img/gfx/java2d/redrock.jpg" alt="Red Rock">
<div class="figure">Figure: Red Rock</div>


<h2>Grayscale image</h2>


<p>
In computing, a grayscale  digital image is an image in which the value 
of each pixel is a single sample, that is, it carries the full (and only) 
information about its intensity. Images of this sort are composed exclusively 
of shades of neutral gray, varying from black at the weakest intensity to 
white at the strongest. (wikipedia)
</p>

<p>
In the next example, we will create a grayscale image with Java 2D tools. 
</p>


<div class="codehead">GrayImage.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class GrayImage extends JPanel {

    Image castle;
    BufferedImage bufferedImage;
    Dimension size;

    public GrayImage() {

        size = new Dimension();
        castle = new ImageIcon("slanec.jpg").getImage();
        size = new Dimension();
        size.width = castle.getWidth(null);
        size.height = castle.getHeight(null);
        setPreferredSize(size);


        bufferedImage =  new BufferedImage(size.width, size.height, 
                             BufferedImage.TYPE_BYTE_GRAY);

        Graphics g = bufferedImage.getGraphics();
        g.drawImage(castle, 0, 0, null);
        g.dispose();
    }

    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(bufferedImage, null, 0, 0);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Grayscale");
        frame.add(new GrayImage());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
Creating a grayscale image is very easy in Java 2D. 
</p>


<pre class="explanation">
bufferedImage = new BufferedImage(size.width, size.height, 
                    BufferedImage.TYPE_BYTE_GRAY);
</pre>

<p>
All we have to do is create a <code>BufferedImage</code> 
class of type <code>BufferedImage.TYPE_BYTE_GRAY</code>.
</p>


<pre class="explanation">
Graphics g = bufferedImage.getGraphics();
g.drawImage(castle, 0, 0, null);
</pre>

<p>
Here we draw the image of the castle into the buffered image. 
</p>

<pre class="explanation">
g.dispose();
</pre>

<p>
Resources are released. 
</p>

<img src="/img/gfx/java2d/grayscale.png" alt="Grayscale">
<div class="figure">Figure: Grayscale</div>


<h2>Flipped image</h2>


<p>
Next we are going to flip an image. We are going to <b>filter the image</b>. 
There is a <code>filter()</code>
method, which is transforming images. 
</p>

<div class="codehead">ImageFlip.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class ImageFlip extends JPanel {

    Image castle;
    BufferedImage bufferedImage;

    public ImageFlip() {
        castle = new ImageIcon("slanec.jpg").getImage();
        bufferedImage =  new BufferedImage(castle.getWidth(null), 
                 castle.getHeight(null), BufferedImage.TYPE_INT_RGB);
    }

    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        Graphics gb = bufferedImage.getGraphics();
        gb.drawImage(castle, 0, 0, null);
        gb.dispose();

        AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
        tx.translate(-castle.getWidth(null), 0);
        AffineTransformOp op = new AffineTransformOp(tx, 
                                AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        bufferedImage = op.filter(bufferedImage, null);

        g2d.drawImage(castle, 10, 10, null);
        g2d.drawImage(bufferedImage, null, 290, 10);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Flip image");
        frame.add(new ImageFlip());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(570, 230);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
In our code example, we horizontally flip our image. 
</p>


<pre class="explanation">
AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
tx.translate(-castle.getWidth(null), 0);
</pre>

<p>
Flipping an image means scaling it and translating it. So we do an 
<code>AffineTransform</code> operation.
</p>


<pre class="explanation">
AffineTransformOp op = new AffineTransformOp(tx, 
                        AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
bufferedImage = op.filter(bufferedImage, null)
</pre>

<p>
This is one of the filtering operations available. This could be also 
done by pixel manipulation. But Java 2D provides
high level classes, that make it easier to manipulate images. 
In our case, the <code>AffineTransformOp</code> class 
performs scaling and translation on the image pixels. 
</p>

<pre class="explanation">
g2d.drawImage(castle, 10, 10, null);
g2d.drawImage(bufferedImage, null, 290, 10);
</pre> 

<p>
Finally, we draw both images to see the difference. 
</p>

<img src="/img/gfx/java2d/flipped.jpg" alt="Flipped image">
<div class="figure">Figure: Flipped image</div>



<h2>Blurred image</h2>


<p>
The next code example will blur our image. Blur means an unfocused image.
To blur an image, we use the convolution operation. It is a mathematical 
operations. It is also used in edge detection or
noise elimination. Blur operations can be used in various graphical effects. 
For example creating speed illusion, showing 
an unfocused vision of a human being etc. 
</p>

<p>
The blur filter operation replaces each pixel in image with an average 
of the pixel and its neighbours. 
</p>

<div class="codehead">BlurredImage.java</div>
<pre class="code">
package com.zetcode;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import java.io.IOException;

import javax.imageio.ImageIO;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class BlurredImage extends JPanel {

    BufferedImage castle;
    BufferedImage filteredImage;
    Dimension size;

    public BlurredImage() {

        try {
            castle = ImageIO.read(this.getClass().getResource("redrock.png"));
        } catch (IOException e) {
            System.out.println("cannot read image");
        }

        filteredImage = new BufferedImage(castle.getWidth(null),
                                          castle.getHeight(null),
                                          BufferedImage.TYPE_BYTE_GRAY);

        size = new Dimension();
        size.width = castle.getWidth(null);
        size.height = castle.getHeight(null);
        setPreferredSize(size);

        Graphics g = filteredImage.getGraphics();
        g.drawImage(castle, 455, 255, null);

        float[] blurKernel = {
            1/9f, 1/9f, 1/9f,
            1/9f, 1/9f, 1/9f,
            1/9f, 1/9f, 1/9f
        };

        BufferedImageOp blur = new ConvolveOp(new Kernel(3, 3, blurKernel));
        castle = blur.filter(castle, new BufferedImage(castle.getWidth(),
            castle.getHeight(),castle.getType()));
        g.dispose();
    }

    @Override
    public void paint(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(castle, null, 3, 3);
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Blurred Image");
        frame.add(new BlurredImage());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

</pre>

<p>
Blur.
</p>

<pre class="explanation">
try {
    castle = ImageIO.read(this.getClass().getResource("redrock.png"));
} catch (IOException e) {
    System.out.println("cannot read image");
}
</pre>

<p>
Here we use an alternative method of loading an image in Java 2D. We 
use the <code>read()</code> method
of the <code>ImageIO</code> class. This way we directly 
have a <code>BufferedImage</code> class. 
</p>

<pre class="explanation">
float[] blurKernel = {
    1/9f, 1/9f, 1/9f,
    1/9f, 1/9f, 1/9f,
    1/9f, 1/9f, 1/9f
};
</pre>

<p>
This matrix is called a kernel. The values are weights that are applied 
to the neighbouring values of the pixel being changed. 
</p>

<pre class="explanation">
BufferedImageOp blur = new ConvolveOp(new Kernel(3, 3, blurKernel));
castle = blur.filter(castle, new BufferedImage(castle.getWidth(),
    castle.getHeight(),castle.getType()));
</pre> 

<p>
Here we apply the blur filter to the image. 
</p>


<img src="/img/gfx/java2d/blurred.jpg" alt="Blurred image">
<div class="figure">Figure: Blurred image</div>


<h2>Reflection</h2>

<p>
In the next example we show a reflected image. This beautiful effect makes 
an illusion as if the image was reflected in water. 
</p>


<div class="codehead">Reflection.java</div>
<pre class="code">
package com.zetcode;

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;


public class Reflection extends JComponent {

    private BufferedImage image;

    public Reflection() {
        try {
            image = ImageIO.read(new File("slanec.jpg"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void paintComponent(Graphics g) {

        Graphics2D g2d = (Graphics2D)g;
        int width = getWidth();
        int height = getHeight();
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        int gap = 20;
        float opacity = 0.4f;
        float fadeHeight = 0.3f;

        g2d.setPaint(new GradientPaint(0, 0, Color.black, 0, height,
                                       Color.darkGray));
        g2d.fillRect(0, 0, width, height);
        g2d.translate((width - imageWidth) / 2, height / 2 - imageHeight);
        g2d.drawRenderedImage(image, null);
        g2d.translate(0, 2 * imageHeight + gap);
        g2d.scale(1, -1);

        BufferedImage reflection =
            new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D rg = reflection.createGraphics();
        rg.drawRenderedImage(image, null);
        rg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
        rg.setPaint(new GradientPaint(0, imageHeight * fadeHeight,
                                      new Color(0.0f, 0.0f, 0.0f, 0.0f), 0,
                                      imageHeight,
                                      new Color(0.0f, 0.0f, 0.0f, opacity)));

        rg.fillRect(0, 0, imageWidth, imageHeight);
        rg.dispose();
        g2d.drawRenderedImage(reflection, null);
    }

    public Dimension getPreferredSize() {
        return new Dimension(320, 390);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Reflection");
        Reflection r = new Reflection();
        frame.add(new Reflection());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
</pre>

<p>
Credit goes to <a href="http://www.jhlabs.com/java/java2d/reflections/index.html">jhlabs.com</a>. 
</p>


<pre class="explanation">
g2d.setPaint(new GradientPaint(0, 0, Color.black, 0, height,
                            Color.darkGray));
g2d.fillRect(0, 0, width, height);
</pre>

<p>
The background is filled with a gradient paint. The paint is a smooth blending from black to dark gray. 
</p>


<pre class="explanation">
g2d.translate(0, 2 * imageHeight + gap);
g2d.scale(1, -1);
</pre>

<p>
This code flips the image and translates it below the original image. 
The translation operation is necessary, because the scaling operation 
makes the image upside down and translates the image up. To understand 
what happens, simply take a photograph and place it on the table. Now flip it. 
</p>

<pre class="explanation">
rg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN));
rg.setPaint(new GradientPaint(0, imageHeight * fadeHeight,
        new Color(0.0f, 0.0f, 0.0f, 0.0f), 0,
        imageHeight,
        new Color(0.0f, 0.0f, 0.0f, opacity)));
</pre> 

<p>
This is the most important part of the code. We make the second image transparent. But the transparency is 
not constant. The image gradually fades out. This is achieved with the <code>GradientPaint</code>.
</p>

<img src="/img/gfx/java2d/reflection.jpg" alt="Reflection">
<div class="figure">Figure: Reflection</div>

<p>
In this part of the Java2D tutorial we have worked with images.
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified November 5, 2008  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>


